package cn.myjava.gupao.mode.singleton;

/**
 * 懒汉式单例模式
 * Created by RenFu
 * Date: 2019/5/12
 */
public class LazySimpleSingleton {

    // 先静态、后动态
    // 先属性、后方法
    // 先上后下

    // 第一种写法
    private static LazySimpleSingleton lazySimpleSingleton = null;

    private LazySimpleSingleton() {
        // 防止反射、序列化破坏单例
        if (lazySimpleSingleton != null) {
            throw new RuntimeException("singleton can not create by constract");
        }

        // 不允许构造器创建;
        StackTraceElement stack[] = Thread.currentThread().getStackTrace();
        for (StackTraceElement ste : stack) {
            if (ste.getClassName().equals("java.lang.reflect.Constructor")) {
                throw new RuntimeException("singleton can not create by constract!");
            }
        }
    }

//    /**
//     * <1>
//     * 存在线程安全隐患
//     */
//    public static LazySimpleSingleton getInstance() {
//        if (lazySimpleSingleton != null) {
//            lazySimpleSingleton = new LazySimpleSingleton();
//        }
//        return lazySimpleSingleton;
//    }

    /**
     * <2>
     * 使用synchronized关键字解决线程安全问题
     * 在线程数量较多的情况下，使用synchronized关键字会导致大量线程出现阻塞，从而导致程序性能大幅下降
     *
     * synchronized在方法级别，阻塞是基于整个类的阻塞
     */
//    public static synchronized LazySimpleSingleton getInstance() {
//        if (lazySimpleSingleton != null) {
//            lazySimpleSingleton = new LazySimpleSingleton();
//        }
//        return lazySimpleSingleton;
//    }

    /**
     * <3>
     * 使用双重锁解决synchronized关键字导致的性能下降问题
     *
     * synchronized在方法内，阻塞是基于方法getInstance(),只要逻辑不太复杂，对于调用这来说几乎感知不到
     */
    public static LazySimpleSingleton getInstance() {
        // 第一重锁
        if (lazySimpleSingleton == null) {
            synchronized(LazySimpleSingleton.class) {
                // 第二重锁
                if (lazySimpleSingleton == null) {
                    lazySimpleSingleton = new LazySimpleSingleton();
                }
            }
        }
        return lazySimpleSingleton;
    }

}
